#include "calculateitem7testjson.h"
#include <stdexcept>

// 全局变量定义
QHash<QString, CJgOrder*> orderId2Order;
QHash<QString, double> processUrgentLevels;

void CalculateItem7TestJson::initTestCase()
{
    qDebug() << "=== 初始化 CalculateItem_7 JSON测试 ===";

    testDataFileBase = getTestDataBasePath();
    testResultFileBase = getTestResultBasePath();

    qDebug() << "测试数据基础路径:" << testDataFileBase;
    qDebug() << "测试结果基础路径:" << testResultFileBase;

    QDir testDataDir(testDataFileBase);
    if (!testDataDir.exists()) {
        qFatal("❌ 测试数据目录不存在: %s", testDataFileBase.toUtf8().constData());
    }

    QDir testResultDir(testResultFileBase);
    if (!testResultDir.exists()) {
        if (testResultDir.mkpath(".")) {
            qDebug() << "✅ 测试结果目录创建成功";
        } else {
            qWarning() << "❌ 测试结果目录创建失败";
        }
    }

    qDebug() << "✅ CalculateItem_7 JSON测试环境初始化完成";
}

void CalculateItem7TestJson::cleanupTestCase()
{
    qDebug() << "=== 清理 CalculateItem_7 JSON测试 ===";
    // 清理全局变量
    qDeleteAll(::orderId2Order);
    ::orderId2Order.clear();
    ::processUrgentLevels.clear();
    qDebug() << "✅ 测试环境清理完成";
}

QString CalculateItem7TestJson::getTestDataBasePath()
{
    QDir currentDir(QDir::currentPath());
    QDir targetDir = currentDir.filePath("../../../../../test_data");
    QString absolutePath = targetDir.absolutePath() + "/";

    if (targetDir.exists()) {
        qDebug() << "✅ 使用相对路径找到测试数据:" << absolutePath;
        return absolutePath;
    } else {
        qWarning() << "❌ 相对路径找不到测试数据，使用硬编码路径";
        return "D:/Work/algorithm-test/test_data/";
    }
}

QString CalculateItem7TestJson::getTestResultBasePath()
{
    QDir currentDir(QDir::currentPath());
    QDir targetDir = currentDir.filePath("../../../../../test_result");
    QString absolutePath = targetDir.absolutePath() + "/";

    if (targetDir.exists()) {
        qDebug() << "✅ 使用相对路径找到测试结果路径:" << absolutePath;
        return absolutePath;
    } else {
        if (targetDir.mkpath(".")) {
            qDebug() << "✅ 创建测试结果路径:" << absolutePath;
            return absolutePath;
        } else {
            qWarning() << "❌ 无法创建测试结果路径，使用硬编码路径";
            return "D:/Work/algorithm-test/test_result/";
        }
    }
}

QJsonObject CalculateItem7TestJson::readJsonObject(const QString& filePath)
{
    qDebug() << "读取JSON对象文件:" << filePath;

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        QString errorMsg = QString("无法打开文件：%1").arg(filePath);
        qWarning() << errorMsg;
        throw std::runtime_error(errorMsg.toStdString());
    }

    QByteArray data = file.readAll();
    file.close();

    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (doc.isNull()) {
        qWarning() << "JSON解析失败，文件内容:" << QString(data).left(100) << "...";
        throw std::runtime_error("JSON解析失败");
    }

    if (!doc.isObject()) {
        qWarning() << "JSON不是对象格式";
        throw std::runtime_error("JSON不是对象格式");
    }

    return doc.object();
}

QJsonArray CalculateItem7TestJson::readJsonArray(const QString& filePath)
{
    qDebug() << "读取JSON数组文件:" << filePath;

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        QString errorMsg = QString("无法打开文件：%1").arg(filePath);
        qWarning() << errorMsg;
        throw std::runtime_error(errorMsg.toStdString());
    }

    QByteArray data = file.readAll();
    file.close();

    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (doc.isNull()) {
        qWarning() << "JSON解析失败，文件内容:" << QString(data).left(100) << "...";
        throw std::runtime_error("JSON解析失败");
    }

    if (!doc.isArray()) {
        qWarning() << "JSON不是数组格式";
        throw std::runtime_error("JSON不是数组格式");
    }

    return doc.array();
}

void CalculateItem7TestJson::createFileRecursion(const QString& fileName)
{
    QFileInfo fileInfo(fileName);
    QDir dir = fileInfo.absoluteDir();

    if (!dir.exists()) {
        dir.mkpath(".");
    }

    QFile file(fileName);
    if (!file.exists()) {
        file.open(QIODevice::WriteOnly);
        file.close();
    }
}

void CalculateItem7TestJson::loadTestData(const QString& folderPath, CSchProcessPosition& processor)
{
    qDebug() << "加载测试数据:" << folderPath;
    
    try {
        // 1. 加载订单映射表 orderId2Order.json
        QString orderId2OrderPath = folderPath + "orderId2Order.json";
        QFile orderId2OrderFile(orderId2OrderPath);
        if (orderId2OrderFile.exists()) {
            QJsonObject orderId2Order = readJsonObject(orderId2OrderPath);
            qDebug() << "加载订单映射表数量:" << orderId2Order.keys().size();
            
            // 清空并设置订单映射表
            qDeleteAll(::orderId2Order);
            ::orderId2Order.clear();
            for (auto it = orderId2Order.begin(); it != orderId2Order.end(); ++it) {
                QString orderNum = it.key();
                QJsonObject orderObj = it.value().toObject();
                
                CJgOrder* orderDto = new CJgOrder();
                orderDto->mLocalOrderNum = orderNum;
                orderDto->mColor = orderObj["mColor"].toString();
                orderDto->mLineColorNum = orderObj["mLineColorNum"].toString();
                orderDto->mOuterOrderNum = orderObj["mOuterOrderNum"].toString();
                orderDto->mbPriFlag = orderObj["mbPriFlag"].toBool();
                
                ::orderId2Order[orderNum] = orderDto;
            }
        } else {
            qDebug() << "警告：orderId2Order.json 文件不存在:" << orderId2OrderPath;
            qDeleteAll(::orderId2Order);
            ::orderId2Order.clear();
        }

        // 2. 加载工序加急等级映射 processUrgentLevels.json
        QString processUrgentLevelsPath = folderPath + "processUrgentLevels.json";
        QFile processUrgentLevelsFile(processUrgentLevelsPath);
        if (processUrgentLevelsFile.exists()) {
            QJsonObject processUrgentLevels = readJsonObject(processUrgentLevelsPath);
            qDebug() << "加载工序加急等级映射数量:" << processUrgentLevels.keys().size();
            
            // 清空并设置工序加急等级映射
            ::processUrgentLevels.clear();
            for (auto it = processUrgentLevels.begin(); it != processUrgentLevels.end(); ++it) {
                QString levelCode = it.key();
                double levelValue = it.value().toDouble();
                ::processUrgentLevels[levelCode] = levelValue;
            }
        } else {
            qDebug() << "警告：processUrgentLevels.json 文件不存在:" << processUrgentLevelsPath;
            ::processUrgentLevels.clear();
        }

        // 3. 加载工序集 hProcessSet.json
        QString hProcessSetPath = folderPath + "hProcessSet.json";
        QFile hProcessSetFile(hProcessSetPath);
        if (hProcessSetFile.exists()) {
            QJsonObject hProcessSet = readJsonObject(hProcessSetPath);
            qDebug() << "加载工序集数量:" << hProcessSet.keys().size();
            
            // 清空并设置工序集
            qDeleteAll(processor.ProcessPosition.hProcessSet);
            processor.ProcessPosition.hProcessSet.clear();
            for (auto it = hProcessSet.begin(); it != hProcessSet.end(); ++it) {
                qlonglong processId = it.key().toLongLong();
                QJsonObject processObj = it.value().toObject();
                
                QJsonObject orderObj = processObj["pOrder"].toObject();
                QString orderNum = orderObj["mLocalOrderNum"].toString();
                CJgOrder* orderDto = ::orderId2Order.value(orderNum, nullptr);
                if (!orderDto) {
                    orderDto = new CJgOrder();
                    orderDto->mLocalOrderNum = orderNum;
                    orderDto->mColor = orderObj["mColor"].toString();
                    orderDto->mLineColorNum = orderObj["mLineColorNum"].toString();
                    orderDto->mOuterOrderNum = orderObj["mOuterOrderNum"].toString();
                    orderDto->mbPriFlag = orderObj["mbPriFlag"].toBool();
                    ::orderId2Order[orderNum] = orderDto;
                }
                
                CJgOrderProcess* orderProcess = new CJgOrderProcess();
                orderProcess->miProcessId = processObj["orderProcessId"].toVariant().toLongLong();
                orderProcess->pOrder = orderDto;
                
                // 创建并设置调度信息
                CJgProcessSchedule* scheduling = new CJgProcessSchedule();
                if (processObj.contains("mscheduling") && processObj["mscheduling"].isObject()) {
                    QJsonObject schedulingObj = processObj["mscheduling"].toObject();
                    scheduling->mbHoldFlag = schedulingObj["mbHoldFlag"].toBool();
                    scheduling->mbNGFlag = schedulingObj["mbNGFlag"].toBool();
                    scheduling->mbUrgentFlag = schedulingObj["mbUrgentFlag"].toBool();
                    
                    // 设置可做工位集合
                    if (schedulingObj.contains("mposCanDo") && schedulingObj["mposCanDo"].isArray()) {
                        QJsonArray posCanDoArray = schedulingObj["mposCanDo"].toArray();
                        for (const QJsonValue& posValue : posCanDoArray) {
                            scheduling->mPosCanDo.append(posValue.toVariant().toInt());
                        }
                    }
                } else {
                    qDebug() << "工序" << processId << "缺少mscheduling对象或不是对象类型";
                    qDebug() << "processObj keys:" << processObj.keys();
                }
                
                orderProcess->mScheduling = scheduling;
                processor.ProcessPosition.hProcessSet[processId] = orderProcess;
            }
        } else {
            qDebug() << "警告：hProcessSet.json 文件不存在:" << hProcessSetPath;
            qDeleteAll(processor.ProcessPosition.hProcessSet);
            processor.ProcessPosition.hProcessSet.clear();
        }

        // 4. 加载可排产的工位 sPositionsScore.json
        QString sPositionsScorePath = folderPath + "sPositionsScore.json";
        QFile sPositionsScoreFile(sPositionsScorePath);
        if (sPositionsScoreFile.exists()) {
            QJsonArray sPositionsScore = readJsonArray(sPositionsScorePath);
            qDebug() << "加载可排产的工位数量:" << sPositionsScore.size();
            
            // 清空并设置可排产的工位
            processor.ProcessPosition.sPositionsScore.clear();
            for (const QJsonValue& value : sPositionsScore) {
                processor.ProcessPosition.sPositionsScore.insert(value.toVariant().toInt());
            }
        } else {
            qDebug() << "警告：sPositionsScore.json 文件不存在:" << sPositionsScorePath;
            processor.ProcessPosition.sPositionsScore.clear();
        }

        // 5. 加载按工序查找的分数表 hScoreByProcess.json
        QString hScoreByProcessPath = folderPath + "hScoreByProcess.json";
        QFile hScoreByProcessFile(hScoreByProcessPath);
        if (hScoreByProcessFile.exists()) {
            QJsonObject hScoreByProcess = readJsonObject(hScoreByProcessPath);
            qDebug() << "加载按工序查找的分数表数量:" << hScoreByProcess.keys().size();
            
            // 清理hScoreByProcess中的SSCORE对象
            for (auto it = processor.ProcessPosition.hScoreByProcess.begin(); 
                 it != processor.ProcessPosition.hScoreByProcess.end(); ++it) {
                qDeleteAll(*it);
            }
            processor.ProcessPosition.hScoreByProcess.clear();
            
            // 设置按工序查找的分数表
            for (auto it = hScoreByProcess.begin(); it != hScoreByProcess.end(); ++it) {
                qlonglong processId = it.key().toLongLong();
                QJsonArray scoresArray = it.value().toArray();
                
                QVector<SSCORE*> scores;
                for (const QJsonValue& scoreValue : scoresArray) {
                    QJsonObject scoreObj = scoreValue.toObject();
                    SSCORE* score = new SSCORE();
                    score->Position = scoreObj["positionId"].toVariant().toInt();
                    score->Total = scoreObj["total"].toDouble();
                    
                    // 初始化分数项数组
                    QJsonArray scoreItemsArray = scoreObj["scoreItem"].toArray();
                    for (int i = 0; i < qMin(scoreItemsArray.size(), _MAX_SCORE_ITEM_); ++i) {
                        score->ScoreItem[i] = scoreItemsArray[i].toDouble();
                    }
                    
                    scores.append(score);
                }
                
                processor.ProcessPosition.hScoreByProcess[processId] = scores;
            }
        } else {
            qDebug() << "警告：hScoreByProcess.json 文件不存在:" << hScoreByProcessPath;
            // 清理hScoreByProcess中的SSCORE对象
            for (auto it = processor.ProcessPosition.hScoreByProcess.begin(); 
                 it != processor.ProcessPosition.hScoreByProcess.end(); ++it) {
                qDeleteAll(*it);
            }
            processor.ProcessPosition.hScoreByProcess.clear();
        }
        
        // 建立工序和工位之间的关联
        for (auto it = processor.ProcessPosition.hProcessSet.begin(); 
             it != processor.ProcessPosition.hProcessSet.end(); ++it) {
            CJgOrderProcess* process = it.value();
            // 为每个工序添加所有可排产的工位到可执行工位列表中
            for (int position : processor.ProcessPosition.sPositionsScore) {
                process->mScheduling->mPosCanDo.append(position);
            }
        }
        
        // 添加调试信息：输出所有工序及其mPosCanDo信息
        qDebug() << "=== 工序 mPosCanDo 信息 ===";
        for (auto it = processor.ProcessPosition.hProcessSet.begin(); 
             it != processor.ProcessPosition.hProcessSet.end(); ++it) {
            CJgOrderProcess* process = it.value();
            QString posCanDoStr = "mPosCanDo: [";
            for (int i = 0; i < process->mScheduling->mPosCanDo.size(); ++i) {
                if (i > 0) posCanDoStr += ", ";
                posCanDoStr += QString::number(process->mScheduling->mPosCanDo.at(i));
            }
            posCanDoStr += "]";
            qDebug() << "工序ID:" << it.key() << posCanDoStr;
        }
        qDebug() << "========================";
        
    } catch (const std::exception& e) {
        qWarning() << "加载测试数据异常:" << e.what();
        throw;
    }
}

void CalculateItem7TestJson::testSingleCase(const QString& folderPath, const QString& resultFileName)
{
    qDebug() << "测试用例路径:" << folderPath;

    try {
        // 1. 创建 CSchProcessPosition 实例
        CSchProcessPosition schProcessPosition;
        
        // 2. 加载测试数据
        loadTestData(folderPath, schProcessPosition);
        
        // 3. 读取函数参数
        double ratio = 0.0;
        QString testCasesPath = folderPath + "testCases.json";
        QFile testCasesFile(testCasesPath);
        if (testCasesFile.exists()) {
            QJsonObject functionParams = readJsonObject(testCasesPath);
            ratio = functionParams["ratio"].toDouble();
            qDebug() << "测试参数 ratio:" << ratio;
        } else {
            qDebug() << "警告：testCases.json 文件不存在，使用默认 ratio 值:" << ratio;
        }

        // 4. 调用 CalculateItem_7 方法前的状态
        qDebug() << "调用CalculateItem_7前的processor状态:";
        qDebug() << "  hProcessSet.size():" << schProcessPosition.ProcessPosition.hProcessSet.size();
        qDebug() << "  sPositionsScore.size():" << schProcessPosition.ProcessPosition.sPositionsScore.size();
        qDebug() << "  hScoreByProcess.size():" << schProcessPosition.ProcessPosition.hScoreByProcess.size();
        
        // 添加更多调试信息
        qDebug() << "=== 调用前详细信息 ===";
        const QHash<qlonglong, QVector<SSCORE*>>& scoreByProcessBefore = schProcessPosition.getScoreByProcess();
        QList<qlonglong> keysBefore = scoreByProcessBefore.keys();
        std::sort(keysBefore.begin(), keysBefore.end());
        
        for (qlonglong processId : keysBefore) {
            QVector<SSCORE*> scores = scoreByProcessBefore[processId];
            qDebug() << "工序ID:" << processId << "分数数量:" << scores.size();
            for (SSCORE* score : scores) {
                qDebug() << "  工位ID:" << score->Position 
                         << "总分:" << QString::number(score->Total, 'f', 4)
                         << "ScoreItem[6]: " << QString::number(score->ScoreItem[6], 'f', 4);
            }
        }
        qDebug() << "====================";

        // 5. 调用 CalculateItem_7 方法
        qDebug() << "调用 CalculateItem_7 方法，参数 ratio=" << ratio;
        try {
            schProcessPosition.CalculateItem_7(static_cast<float>(ratio));
            qDebug() << "CalculateItem_7 方法执行完成";
        } catch (const std::exception& e) {
            qWarning() << "CalculateItem_7 执行异常:" << e.what();
            throw;
        } catch (...) {
            qWarning() << "CalculateItem_7 执行未知异常";
            throw;
        }

        // 6. 调用 CalculateItem_7 后的状态
        qDebug() << "调用CalculateItem_7后的processor状态:";
        qDebug() << "  hProcessSet.size():" << schProcessPosition.ProcessPosition.hProcessSet.size();
        qDebug() << "  sPositionsScore.size():" << schProcessPosition.ProcessPosition.sPositionsScore.size();
        qDebug() << "  hScoreByProcess.size():" << schProcessPosition.ProcessPosition.hScoreByProcess.size();

        // 7. 写入结果文件
        createFileRecursion(resultFileName);
        QFile resultFile(resultFileName);
        if (resultFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream stream(&resultFile);
            
            // 输出处理后的分数信息
            // 遍历 hScoreByProcess 输出结果（按键排序）
            const QHash<qlonglong, QVector<SSCORE*>>& scoreByProcess = schProcessPosition.getScoreByProcess();
            bool hasData = false;
            qDebug() << "scoreByProcess.size():" << scoreByProcess.size();
            
            // 获取所有键并排序
            QList<qlonglong> keys = scoreByProcess.keys();
            std::sort(keys.begin(), keys.end());
            
            // 按排序后的键顺序输出
            for (qlonglong processId : keys) {
                QVector<SSCORE*> scores = scoreByProcess[processId];
                
                stream << "Process ID: " << processId << "\n";
                qDebug() << "Process ID:" << processId << "Scores count:" << scores.size();
                
                for (SSCORE* score : scores) {
                    stream << "  Position ID: " << score->Position
                           << ", Total Score: " << QString::number(score->Total, 'f', 4)
                           << ", Score Item [6]: " << QString::number(score->ScoreItem[6], 'f', 4) << "\n";
                    hasData = true;
                    qDebug() << "  Position ID:" << score->Position 
                             << ", Total Score:" << QString::number(score->Total, 'f', 4)
                             << ", Score Item [6]:" << QString::number(score->ScoreItem[6], 'f', 4);
                }
            }
            
            if (!hasData) {
                stream << "无数据输出\n";
                qDebug() << "无数据输出";
            }
            
            resultFile.close();
            qDebug() << "结果写入:" << resultFileName;
        }

    } catch (const std::exception& e) {
        qWarning() << "测试用例执行失败:" << e.what();
        // 写入错误结果
        createFileRecursion(resultFileName);
        QFile resultFile(resultFileName);
        if (resultFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream stream(&resultFile);
            stream << "测试失败: " << e.what() << "\n";
            resultFile.close();
        }
    }
}

void CalculateItem7TestJson::testCalculateItem7FromJson()
{
    qDebug() << "=== 开始使用JSON数据测试 CalculateItem_7 方法 ===";

    QString testPath = getTestDataBasePath() + "calculateItem_7/";
    QString resultPath = getTestResultBasePath() + "calculateItem_7_c/";
    
    // 确保结果目录存在
    QDir resultDir(resultPath);
    if (!resultDir.exists()) {
        resultDir.mkpath(".");
    }
    
    // 遍历测试用例
    for (int i = 1; i <= 52; i++) {
        try {
            QString folderPath;
            QString resultFileName;

            if (i <= 50) {
                folderPath = testDataFileBase + QString("calculateItem_7/random_case_%1/").arg(i);
                resultFileName = testResultFileBase + QString("calculateItem_7_c/random_case_%1.txt").arg(i);
            } else {
                folderPath = testDataFileBase + QString("calculateItem_7/manual_case_%1/").arg(i - 50);
                resultFileName = testResultFileBase + QString("calculateItem_7_c/manual_case_%1.txt").arg(i - 50);
            }

            QDir folder(folderPath);
            if (!folder.exists()) {
                qWarning() << "文件夹不存在：" << folderPath;
                continue;
            }

            qDebug() << "\n=== 处理测试用例" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50)) << "===";

            // 测试单个用例
            testSingleCase(folderPath, resultFileName);

            qDebug() << "测试完成:" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50));

        } catch (const std::exception& e) {
            qWarning() << "测试失败:" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50)) << "错误:" << e.what();
        }
    }
}
